#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <numeric>
using namespace std;

class Solution {
        vector<int> father;
        int find(int x)
        {
                return father[x] == x ? x : father[x] = find(father[x]);
        }

        bool merge(int x, int y)
        {
                int fx = find(x);
                int fy = find(y);
                if(fx == fy){
                        return false;
                }else{
                        father[fx] = fy;
                        return true;
                }
        }
public:
        int max_edges(vector<vector<int>> &edges, int n)
        {
                father.resize(n + 1);
                iota(father.begin(), father.end(), 0);

                sort(edges.begin(), edges.end(), [](auto &a, auto &b){ return a[2] < b[2]; });

                int ans = 0;
                for(int i = 0; i < edges.size(); i++){
                        if(merge(edges[i][0], edges[i][1])){
                                ans = max(ans, edges[i][2]);
                        }
                }
                return ans;
        }
};

int main()
{
        int n = 0, m = 0;
        cin >> n >> m;
        vector<vector<int>> edges;
        for(int i = 0; i < m; i++){
                int u, v, w;
                cin >> u >> v >> w;
                edges.push_back({u, v, w});
        }
        int ans = Solution().max_edges(edges, n);
        cout<<n - 1<<" "<<ans<<endl;
        return 0;
}